//
//  CYLabel.m
//  LingLingBang
//
//  Created by 郝俊聪 on 16/1/15.
//  Copyright © 2016年 zhaohongling. All rights reserved.
//

#import "CYLabel.h"
#import <CoreText/CoreText.h>
#import "CYTextAttachment.h"

@interface CYLabel()<UIAlertViewDelegate,UIGestureRecognizerDelegate>
//正则出的url
@property (nonatomic , strong) NSMutableArray *urlMatches;
//记录连接
@property (nonatomic, strong) NSURL *url;
//打电话辅助控件
@property (nonatomic, strong)UIWebView *phoneWebView;
//menuView
@property (nonatomic, strong) UIMenuController *menuController;
//记录点击结果（自己是否响应点击事件）
@property (nonatomic, assign) BOOL tapResult;

@end

@implementation CYLabel

///重写set方法
- (void)setAttributedText:(NSAttributedString *)attributedText
{
    [super setAttributedText:attributedText];
    if (!attributedText) {
        return;
    }
    //增加长按手势
    [self addLongPressGes];
    dispatch_async(dispatch_get_global_queue(0,0), ^{
        //开辟子线程
        NSAttributedString *attrStr = [self setURLStrTextColorAndAction:attributedText];
        dispatch_async(dispatch_get_main_queue(), ^{
            //主线程回调
            super.attributedText = attrStr;
        });
    });
}

///设置文本带url的蓝色
- (NSAttributedString *)setURLStrTextColorAndAction:(NSAttributedString *)attrStr
{
    NSMutableAttributedString *mutableAttrStr = [[NSMutableAttributedString alloc] initWithAttributedString:attrStr];
    //清除手势
    if (self.gestureRecognizers.count > 0) {
        for (UIGestureRecognizer *ges in self.gestureRecognizers) {
            if ([ges isKindOfClass:[UITapGestureRecognizer class]]) {
               [self removeGestureRecognizer:ges];
            }
        }
    }
    //清除记录的url
    self.url = nil;
    NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink|NSTextCheckingTypePhoneNumber error:nil];
    //先清空
    [_urlMatches removeAllObjects];
    _urlMatches = [NSMutableArray arrayWithArray:[detector matchesInString:attrStr.string options:0 range:NSMakeRange(0, attrStr.string.length)]];
    if (_urlMatches.count > 0) {
        //如果有数据，遍历
        for (NSTextCheckingResult *result in _urlMatches) {
            NSRange range = result.range;
            //设置字体颜色
            [mutableAttrStr addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithHexString:kBuleColor] range:range];
            //增加点击事件
            UITapGestureRecognizer *tapGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickURLStr:)];
            tapGes.delegate = self;
            [self addGestureRecognizer:tapGes];
        }
    }
    return mutableAttrStr;
}

//手势执行的方法
- (void)clickURLStr:(UITapGestureRecognizer *)tapGes
{
    UITapGestureRecognizer *tap = (UITapGestureRecognizer *)tapGes;
    //获取点击坐标
    CGPoint point = [tap locationInView:self];
    //获取点击到字符的位置
    CFIndex charIndex = [self characterIndexAtPoint:point];
    for (NSTextCheckingResult *match in _urlMatches) {
        NSRange matchRange = [match range];
        //如果点到到url的字符，则打开链接
        if ([match resultType] == NSTextCheckingTypeLink) {
            if ([self isIndex:charIndex inRange:matchRange]) {
                NSURL *url = match.URL;
                //记录
                self.url = url;
                //弹框提示
                [self showAlertViewWith:[url absoluteString]];
                break;
            }
        }
        //如果是电话号码
        if ([match resultType] == NSTextCheckingTypePhoneNumber) {
            if ([self isIndex:charIndex inRange:matchRange]) {
                NSString *phoneNumber = match.phoneNumber;
                //拼接电话请求
                NSString *URLStr = [NSString stringWithFormat:@"tel://%@",phoneNumber];
                [self.phoneWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:URLStr]]];
                break;
            }
        }
    }
}

//点击到字符的位置
- (CFIndex)characterIndexAtPoint:(CGPoint)point
{
    NSMutableAttributedString* optimizedAttributedText = [self.attributedText mutableCopy];
    
    [self.attributedText enumerateAttributesInRange:NSMakeRange(0, [self.attributedText length]) options:0 usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) {
        
        if (!attrs[(NSString*)kCTFontAttributeName])
        {
            [optimizedAttributedText addAttribute:(NSString*)kCTFontAttributeName value:self.font range:NSMakeRange(0, [self.attributedText length])];
        }
        
        if (!attrs[(NSString*)kCTParagraphStyleAttributeName])
        {
            NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
            [paragraphStyle setLineBreakMode:self.lineBreakMode];
            [optimizedAttributedText addAttribute:(NSString*)kCTParagraphStyleAttributeName value:paragraphStyle range:range];
        }
    }];
    
    // modify kCTLineBreakByTruncatingTail lineBreakMode to kCTLineBreakByWordWrapping
    [optimizedAttributedText enumerateAttribute:(NSString*)kCTParagraphStyleAttributeName inRange:NSMakeRange(0, [optimizedAttributedText length]) options:0 usingBlock:^(id value, NSRange range, BOOL *stop)
     {
         NSMutableParagraphStyle* paragraphStyle = [value mutableCopy];
         
         if ([paragraphStyle lineBreakMode] == NSLineBreakByTruncatingTail) {
             [paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping];
         }
         [optimizedAttributedText removeAttribute:(NSString*)kCTParagraphStyleAttributeName range:range];
         [optimizedAttributedText addAttribute:(NSString*)kCTParagraphStyleAttributeName value:paragraphStyle range:range];
     }];
    
    if (!CGRectContainsPoint(self.bounds, point)) {
        return NSNotFound;
    }
    
    CGRect textRect = self.bounds;
    
    if (!CGRectContainsPoint(textRect, point)) {
        
        return NSNotFound;
        
    }
    
    point = CGPointMake(point.x - textRect.origin.x, point.y - textRect.origin.y);
    point = CGPointMake(point.x, textRect.size.height - point.y);
    
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)optimizedAttributedText);
    
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, textRect);
    
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [self.attributedText length]), path, NULL);
    
    if (frame == NULL) {
        CFRelease(path);
        return NSNotFound;
    }
    
    CFArrayRef lines = CTFrameGetLines(frame);
    
    NSInteger numberOfLines = self.numberOfLines > 0 ? MIN(self.numberOfLines, CFArrayGetCount(lines)) : CFArrayGetCount(lines);
    
    if (numberOfLines == 0) {
        CFRelease(frame);
        CFRelease(path);
        return NSNotFound;
    }
    
    NSUInteger idx = NSNotFound;
    
    CGPoint lineOrigins[numberOfLines];
    CTFrameGetLineOrigins(frame, CFRangeMake(0, numberOfLines), lineOrigins);
    
    for (CFIndex lineIndex = 0; lineIndex < numberOfLines; lineIndex++) {
        
        CGPoint lineOrigin = lineOrigins[lineIndex];
        CTLineRef line = CFArrayGetValueAtIndex(lines, lineIndex);
        
        // Get bounding information of line
        CGFloat ascent, descent, leading, width;
        width = CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
        CGFloat yMin = floor(lineOrigin.y - descent);
        CGFloat yMax = ceil(lineOrigin.y + ascent);
        
        // Check if we've already passed the line
        if (point.y > yMax) {
            break;
        }
        
        // Check if the point is within this line vertically
        if (point.y >= yMin) {
            
            // Check if the point is within this line horizontally
            if (point.x >= lineOrigin.x && point.x <= lineOrigin.x + width) {
                
                // Convert CT coordinates to line-relative coordinates
                CGPoint relativePoint = CGPointMake(point.x - lineOrigin.x, point.y - lineOrigin.y);
                idx = CTLineGetStringIndexForPosition(line, relativePoint);
                
                break;
            }
        }
    }
    CFRelease(frame);
    CFRelease(path);
    return idx;
}

///判断位置是否在范围内
- (BOOL)isIndex:(CFIndex)index inRange:(NSRange)range
{
    return index > range.location && index < range.location+range.length;
}

///弹框提示是否打开连接
- (void)showAlertViewWith:(NSString *)URLStr
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:[NSString stringWithFormat:@"是否打开链接%@？",URLStr] delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"打开", nil];
    alert.delegate = self;
    [alert show];
}

///懒加载电话赋值webview
- (UIWebView *)phoneWebView
{
    if (_phoneWebView == nil) {
        _phoneWebView = [[UIWebView alloc] initWithFrame:CGRectZero];
    }
    return _phoneWebView;
}

#pragma mark - UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 1) {
        //点击了确认按钮
        [[UIApplication sharedApplication] openURL:self.url];
    }
}

#pragma mark - munuVC
-(BOOL)canBecomeFirstResponder

{
    return YES;
}

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender

{
    
    return (action == @selector(copy:));
    
}

//针对于响应方法的实现

-(void)copy:(id)sender

{
    UIPasteboard *pboard = [UIPasteboard generalPasteboard];
    //将属性文本转为普通文本
    NSString *string = [self fullText];
    pboard.string = string;
}

//增加长按手势
- (void)addLongPressGes
{
    UILongPressGestureRecognizer *longGes = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressedLabel:)];
    [self addGestureRecognizer:longGes];
}

//长按按钮
- (void)longPressedLabel:(id)sender
{
    [self becomeFirstResponder];
    [self showMenuViewController];
}

//显示munu控制器
- (void)showMenuViewController
{
    UIMenuController *menuController = [UIMenuController sharedMenuController];
    [menuController setTargetRect:self.frame inView:self.superview];
    [menuController setMenuVisible:YES animated:YES];
}

///将Label中的图片转成字符
- (NSString *)fullText
{   //获得属性文本
    NSAttributedString *attriText = self.attributedText;
    //定义一个字符串用于接收转换的字符
    __block NSString *strM = @"";
    //遍历属性文本
    [attriText enumerateAttributesInRange:NSMakeRange(0, attriText.length) options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired  usingBlock:^(NSDictionary<NSString *,id> * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) {
        //取得附件
        CYTextAttachment *attachment = attrs[@"NSAttachment"];
        if (attachment) {
            //是表情
            strM = [strM stringByAppendingString:attachment.str];
        }else{
            //是文字
            NSString *str = [attriText.string substringWithRange:range];
            //拼接
            strM = [strM stringByAppendingString:str];
        }
    }];
    return strM;
}

#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{

    if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
        return YES;
    }
    //获取点击到字符的位置
    BOOL result = false;
    CGPoint point = [touch locationInView:self];
    CFIndex charIndex = [self characterIndexAtPoint:point];
    for (NSTextCheckingResult *match in _urlMatches) {
        NSRange matchRange = [match range];
        //如果点到到url的字符，则打开链接
        if ([match resultType] == NSTextCheckingTypeLink || [match resultType] == NSTextCheckingTypePhoneNumber) {
            if ([self isIndex:charIndex inRange:matchRange]) {
                result = YES;
                break;
            }else{
                result = NO;
            }
        }else{
            result = NO;
        }
    }
    if (result) {
        return YES;
    }
    return NO;
}



@end
